from functools import wraps
from importlib import import_module
import time
from typing import Any, Dict, Tuple, overload
from lxml import etree
import re

from utils.LogUtil import LogUtil


class CarUtil:

  #定义一个函数用来统计传入函数的运行时间
  def timmer(func):
    """统计传入函数的运行时间

    Args:
        func (function): 传入函数

    Returns:
        function: 传出函数
    """

    # 使用 wraps 防止装饰器重写了我们函数的名字和注释文档(docstring)
    @wraps(func)
    def deco(*args, **kwargs):
      #本应传入运行函数的各种参数
      # print(
      #     '[{date}] 函数: {_funcname_} 开始运行：'.format(
      #         date=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
      #         _funcname_=func.__name__
      #     )
      # )
      LogUtil.debug(f"执行对象：{func.__name__}", title="调度计时器启动")
      start_time = time.time()
      #调用代运行的函数，并将各种原本的参数传入
      res = None
      try:
        func(*args, **kwargs)
      except Exception as ex:
        LogUtil.error(ex, f"计时执行对象 {func.__name__} 发生异常")
      end_time = time.time()
      # print(
      #     '[{date}] 函数: {_funcname_} 运行了{_time_}秒\n'.format(
      #         date=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
      #         _funcname_=func.__name__,
      #         _time_=(end_time - start_time)
      #     )
      # )
      LogUtil.debug(f"计时停止，运行了{end_time - start_time}秒", title="计时器执行完毕")
      #返回值为函数的运行结果

    #返回值为函数
    return deco

  @staticmethod
  # def getJsonFromFile(path):
  def readFromFile(path: str) -> str:
    """从文件读入内容

    Args:
        path (str): 路径

    Returns:
        str: 内容
    """

    with open(path, 'rt') as f:
      text = f.read()
      return text

  # 字典合并
  @staticmethod
  def dictMerge(*args) -> (Tuple[str] | Any | None):
    """字典合并

    Returns:
        (Tuple[str] | Any | None): 结果
    """
    r, *_ = args
    [r.update(args[i]) for i in range(1, len(args)) if args[i]]
    return r

  # 任务模块字典
  @staticmethod
  def loadModules(modules: Dict, *args, **kwargs):
    """加载任务模块

    Args:
        modules (Dict): 任务模块字典
    """
    if modules:
      for module_item in modules:
        try:
          name = module_item.get('name')
          # 根据配置查看是否启用此模块
          if module_item.get("enable"):
            module_name = f'modules.{name}'
            LogUtil.info(title=f"启动模块【{module_name}】")
            module = import_module(module_name)
            module.start(*args, **kwargs)
        except Exception as ex:
          LogUtil.error(ex, f"【{name}】启动失败")
    else:
      LogUtil.info("没有选中任何模块")

  @staticmethod
  def extractByXPath(text: str, pattern: str) -> Any:
    """通过`xpath`提取内容

    Args:
        text (str): 文本内容
        pattern (str): 正则表达式

    Returns:
        Any: 结果
    """

    html = etree.HTML(text)
    return html.xpath(pattern)

  @overload
  @staticmethod
  def extractByRe(text: str, pattern: str, index: int = 0) -> str | None:
    """通过正则提取内容

    Args:
        text (str): 文本内容
        pattern (str): 正则表达式
        index (int, optional): group 索引. Defaults to 0.

    Returns:
        str: 匹配结果
    """
    pass

  @overload
  @staticmethod
  def extractByRe(text: str, pattern: str) -> re.Match:
    """通过正则提取内容

    Args:
        text (str): 文本内容
        pattern (str): 正则表达式

    Returns:
        class re.Match: 匹配结果
    """
    pass

  @staticmethod
  def extractByRe(text, pattern, index=-1) -> re.Match | (str | None):
    match: re.Match = re.search(pattern, string=text)
    if index == -1 or index == None:
      return match
    #endif
    else:
      return match.group(index) if len(match.group()) > 0 else None
    #endif